package com.kmzx.one.project.config.listener;


import com.kmzx.one.common.utils.UUIDGenerator;
import com.kmzx.one.project.entity.UserExchangeRate;
import com.kmzx.one.project.entity.UserInvite;
import com.kmzx.one.project.entity.UserProfit;
import com.kmzx.one.project.entity.UserRank;
import com.kmzx.one.project.entity.UserRankDetail;
import com.kmzx.one.project.entity.UserRankHistory;
import com.kmzx.one.project.events.SelfToUpEvent;
import com.kmzx.one.project.mapper.CustomerMapper;
import com.kmzx.one.project.mapper.UserExchangeRateMapper;
import com.kmzx.one.project.mapper.UserInviteMapper;
import com.kmzx.one.project.mapper.UserProfitMapper;
import com.kmzx.one.project.mapper.UserRankMapper;
import com.kmzx.one.project.others.dso.UserRankDso;
import com.kmzx.one.project.others.dto.UserRankInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Project selections
 * @Author: sunii
 * @Date: 2020/2/13-22:04
 */
@Component("selfToUpEventListener")
public class SelfToUpEventListener {
    private static Logger logger = LoggerFactory.getLogger(SelfToUpEventListener.class);

    @Autowired
    CustomerMapper customerMapper;

    @Autowired
    UserInviteMapper userInviteMapper;

    @Autowired
    UserProfitMapper userProfitMapper;


    @Autowired
    UserRankMapper userRankMapper;

    @Autowired
    ApplicationContext applicationContext;

    @Autowired
    private UserExchangeRateMapper userExchangeRateMapper;

    @Async
    @EventListener(classes = {SelfToUpEvent.class})
    @Transactional(rollbackFor = Exception.class)
    public void defaultSelfToUpEvent(SelfToUpEvent selfToUpEvent) {

        String userId = selfToUpEvent.getSelfUserId();
//        BigDecimal selfRankMoney = selfAndUpEvent.getSelfRankMoney();

        BigDecimal orderMoney = selfToUpEvent.getBuyMoney();
        String orderCodes = selfToUpEvent.getOrderCodes();
        UserRankInfo userRank = userRankMapper.selectUserRankTabs(userId);
        Integer selfRankNo = userRank.getRankNo();
        Date date = new Date();
        // todo 2.查找用户的父级
        UserInvite parentInvite = getUserParentInvite(userId);
        UserExchangeRate userExchangeRate = new UserExchangeRate();
        userExchangeRate.setId(UUIDGenerator.generate());
        userExchangeRate.setUserId(userId);
        userExchangeRate.setOrderId(orderCodes);
        userExchangeRate.setCreateTime(new Date());
        userExchangeRate.setStates(0);


        // todo 2.1 有上级
        if (parentInvite != null) {
            // todo 直接一级的UserId
            String up1UserId = parentInvite.getFromUser();
            UserRankInfo userRankTabs = userRankMapper.selectUserRankTabs(up1UserId);
            int rankNo = userRankTabs.getRankNo();
            // todo 2.2 只有一次奖励
            Map<String, Object> map = new HashMap<>();
            if (rankNo <= selfRankNo) {
                orderMoney = orderMoney.divide(BigDecimal.valueOf(2),2, RoundingMode.HALF_UP);
                map = handleRankProfitDetail(date, up1UserId, userId, orderMoney, "购买货仓返 美颜值", userRankTabs.getRankRate(), selfRankNo, orderCodes, true);
                userExchangeRate.setDirectRate(BigDecimal.ZERO.doubleValue());
            } else {
                map = handleRankProfitDetail(date, up1UserId, userId, orderMoney, "购买货仓返利", userRankTabs.getRankRate(), selfRankNo, orderCodes, false);
                BigDecimal rate = (BigDecimal) map.get("rate");
                userExchangeRate.setDirectRate(rate.doubleValue());
            }
            userExchangeRate.setDirectUserId(up1UserId);

            UserInvite parentInviteL4 = getUserParentInvite(up1UserId);
            if (rankNo != 3) {
                String up2UserId = parentInviteL4.getFromUser();
                UserRankInfo userRankTabs2 = userRankMapper.selectUserRankTabs(up2UserId);
                Map<String, Object> map1;
                if (rankNo <= selfRankNo) {
                    map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), "购买货仓返美颜值", userRankTabs2.getRankRate(), selfRankNo, orderCodes, true);
                    userExchangeRate.setDirectRate(BigDecimal.ZERO.doubleValue());
                } else {
                    if (rankNo >= userRankTabs2.getRankNo()) {
                        map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), "购买货仓返美颜值", userRankTabs2.getRankRate(), selfRankNo, orderCodes, true);
                        userExchangeRate.setDirectRate(BigDecimal.ZERO.doubleValue());
                    } else {
                        map1 = handleRankProfitDetail(date, up2UserId, up1UserId, (BigDecimal) map.get("orderMoney"), "购买货仓返利", userRankTabs2.getRankRate(), selfRankNo, orderCodes, false);
                        BigDecimal rate2 = (BigDecimal) map1.get("rate");
                        userExchangeRate.setTopRate(rate2.doubleValue());
                    }
                }
                userExchangeRate.setTopUserId(up2UserId);
            }

        }
        userExchangeRateMapper.insert(userExchangeRate);
        List<UserRankDso> tabs = userRankMapper.selectAllRankTabs();
        UserRank userRank1 = selfToUpEvent.getUserRank();
        Double myGrowthValue = userRank1.getMyGrowthValue();
        BigDecimal add = selfToUpEvent.getBuyMoney().add(BigDecimal.valueOf(myGrowthValue));

        String rankId = userRank1.getRankId();
        userRank1.setMyGrowthValue(add.doubleValue());
        boolean recode = false;
        int grade = 0;
        for (int i = 0; i < tabs.size(); i++) {
            if (tabs.get(i).getRankId().equals(rankId) && i != tabs.size() - 1) {
                BigDecimal rankPay = tabs.get(i).getRankPay();
                if (rankPay.compareTo(add) <= 0) {
                    userRank1.setRankId(tabs.get(i + 1).getRankId());
                    userRank1.setUpdateTime(new Date());
                    recode = true;
                    grade = tabs.get(i + 1).getRankNum();
                }
            }
        }
        userRankMapper.updateByIdSelective(userRank1);


        if (recode) {
            UserRankHistory history = new UserRankHistory();
            history.setCreateTime(date)
                    .setId(UUIDGenerator.generate())
                    .setUserId(userId)
                    .setNickName(userRank.getNickName())
                    .setRankNumber(grade)
                    .setRankId(userRank1.getRankId());
            history.setTosend(0);

            userRankMapper.insertUserRankHistory(history);
        }
    }


    public UserProfit getUserProfit(String userId) {
        List<UserProfit> userProfits = userProfitMapper.selectByUserId(userId);
        if (!CollectionUtils.isEmpty(userProfits)) {
            UserProfit userProfit = userProfits.get(0);
            return userProfit;
        }
        return null;
    }


    public Map<String, Object> handleRankProfitDetail(Date date, String up1UserId, String userId, BigDecimal orderMoney,
                                                      String remarks, Double rankRate, Integer selfRankNo, String orderId, boolean flag) {
        boolean points = flag;
        UserRankDetail up4 = new UserRankDetail();
        up4.setId(UUIDGenerator.generate());
        up4.setCreateTime(date);

        up4.setUserId(up1UserId);
        up4.setFromUserId(userId);
        up4.setOrdersId(orderId);
        BigDecimal t1 = BigDecimal.ONE;
        if (!flag) {
            t1 = t1.subtract(BigDecimal.valueOf(rankRate));
        }


        BigDecimal up1Bill = orderMoney.multiply(t1);
        up4.setUpMode(1);
        up4.setGrowthValue(up1Bill.doubleValue());
        if (flag) {
            up4.setUpMode(9);
            up4.setGrowthValue(orderMoney.doubleValue());
        }
        up4.setRemark(remarks);

        UserRankInfo up1UserRankInfo = userRankMapper.selectUserRankTabs(up1UserId);

        UserRank up1UserRank = new UserRank();

        up1UserRank.setId(up1UserRankInfo.getUserRankId());
        Double up1OldValue = up1UserRankInfo.getGrowth().doubleValue();

        up1UserRank.setRankId(up1UserRankInfo.getRankId());
        up1UserRank.setUpdateTime(date);
        up1UserRank.setMyGrowthValue(up1OldValue + up1Bill.doubleValue());

        boolean recode = false;
        int grade = up1UserRankInfo.getRankNo();
        List<UserRankDso> rankTabs = userRankMapper.selectAllRankTabs();
        for (int i = 0; i < rankTabs.size(); i++) {
            if (up1UserRank.getRankId().equals(rankTabs.get(i).getRankId())) {
                Double myGrowthValue = up1UserRank.getMyGrowthValue();
                BigDecimal rankPay = rankTabs.get(i).getRankPay();
                if (rankPay.compareTo(BigDecimal.ZERO) > 0 && rankPay.compareTo(BigDecimal.valueOf(myGrowthValue)) <= 0) {
                    String nowId = rankTabs.get(i + 1).getRankId();
                    up1UserRank.setRankId(nowId);
                    recode = true;
                    grade += 1;
                }
            }
        }


        Integer upRankNo = up1UserRankInfo.getRankNo();
        up4.setGrowthValue(up1Bill.doubleValue());
        if (upRankNo <= selfRankNo) {
            up4.setUpMode(9);
            up1UserRank.setMyGrowthValue(orderMoney.add(up1UserRankInfo.getGrowth()).doubleValue());
            points = true;
        } else {
            if (!flag) {

                // 特权
                List<String> specUsers = customerMapper.findSpecificUser();
//                if (CollectionUtils.isEmpty(specUsers)){
//                }
                if (specUsers == null) {

                    UserProfit userProfit = getUserProfit(up1UserId);
                    userProfit.setUpdateTime(date);
                    BigDecimal oldAccount = userProfit.getAccountMoney();
                    BigDecimal oldProfitMoney = userProfit.getProfitMoney();
                    userProfit.setAccountMoney(oldAccount.add(up1Bill));
                    BigDecimal nowProfitMoney = oldProfitMoney.add(up1Bill);
                    userProfit.setProfitMoney(nowProfitMoney);
                    userProfitMapper.updateByIdSelective(userProfit);
                } else {
                    if (!specUsers.contains(up1UserId)) {
                        UserProfit userProfit = getUserProfit(up1UserId);
                        userProfit.setUpdateTime(date);
                        BigDecimal oldAccount = userProfit.getAccountMoney();
                        BigDecimal oldProfitMoney = userProfit.getProfitMoney();
                        userProfit.setAccountMoney(oldAccount.add(up1Bill));
                        BigDecimal nowProfitMoney = oldProfitMoney.add(up1Bill);
                        userProfit.setProfitMoney(nowProfitMoney);
                        userProfitMapper.updateByIdSelective(userProfit);
                    }
                }


            }

        }
        userRankMapper.updateByIdSelective(up1UserRank);
        userRankMapper.insertUserRankDetail(up4);

        if (recode) {
            UserRankHistory history = new UserRankHistory();
            history.setCreateTime(date)
                    .setId(UUIDGenerator.generate())
                    .setUserId(up1UserId)
                    .setNickName(up1UserRankInfo.getNickName())
                    .setRankNumber(grade)
                    .setRankId(up1UserRank.getRankId());
            history.setTosend(0);
            userRankMapper.insertUserRankHistory(history);
        }

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("orderMoney", up1Bill);
        if (flag) {
            hashMap.put("orderMoney", orderMoney.divide(BigDecimal.valueOf(2),2, RoundingMode.HALF_UP));
        }
        hashMap.put("rate", t1);
        hashMap.put("selfRankId", up1UserRank.getRankId());
        hashMap.put("point", points);
        return hashMap;
    }


    public UserInvite getUserParentInvite(String userId) {

        List<UserInvite> invites = userInviteMapper.selectUserInviteByUserId(userId);
        if (!CollectionUtils.isEmpty(invites)) {
            UserInvite userInvite = invites.get(0);
            return userInvite;
        }
        return null;
    }
}
